This disclosure relates to a programmable integrated circuit, and particularly to embedded memory blocks in a programmable integrated circuit device—e.g., a field-programmable gate array (FPGA) or other programmable logic device (PLD). More particularly, this disclosure relates to an enhanced embedded memory block that maintains coherency between concurrent memory reads and writes.
It has become increasingly common to design PLDs to include embedded memory blocks in the form of dedicated hard memory blocks and/or out of soft configurable logic. Such embedded memory blocks may include a concentration of circuitry on a PLD that has been partly or fully hardwired to enable the storage and retrieval of data. Embedded memory blocks may be implemented using soft logic resources such as shift registers or configuration memory (CRAM) look-up table masks (LUT-masks). Embedded memories may also be available (or configurable) with varying sizes, widths, port-counts, and single vs. dual port and/or dual-clock read/write functionality.
Embedded memories store many different types of data and enable a variety of functions. For example, they are employed in a wide range of industrial, wireline, and wireless applications where they may be used for caching data or to maintain load/store tables for packet data, statistics, pointers, etc. Embedded memories are also often used as temporary first-in first-out (FIFO) storage between asynchronous sources and components that access and provide data at varying data widths and clock speeds.
Generally, to retrieve data from a memory, a read address and some control signals (e.g., a clock signal) are presented to the memory, and the stored data located at the specified read address is output one clock cycle later. For write transactions, a write address and write data along with related control signals are presented to the memory, and the write data is stored in the memory at the specified write address. For many existing devices, both transactions may be concurrent on separate ports.
In some applications, data read from memory (“read data”) is pipelined for one or more clock cycles prior to being output. In these instances, the read address must be presented to the memory early so that the read data is available when expected, i.e., during the same clock cycle the read data would have been made available had there been no pipelining. This is necessary, for example, when a read-modify-write command is processed by a pipelined memory circuit—if the read data is not made available early, non-current read data will be modified and written back to the memory location. Presenting the read address early realigns the reads and writes so that the read data is output during the same clock cycle as the corresponding write data is committed to memory.
At the same time, however, presenting the read address to the memory early presents its own challenges. Data written to memory during one clock cycle usually only becomes available during the next clock cycle. Specifically, data written to memory must be committed by the end of a clock cycle in order for that data to be available for reading in the next clock cycle. Presenting the read address to the memory early may therefore result in non-current data being read from the specified memory location. In particular, the read data will not include any data written to the memory location during, or after, the clock cycle in which the read address is presented to the memory. The greater the amount of pipelining introduced into the memory, the more significant the problem.